/**
 * Copyright 2014,Peak Tai 台俊峰(taijunfeng_it@sina.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * 		http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.cenluan.vote;

import java.util.Date;

import com.cenluan.common.Const;
import com.cenluan.ext.jfinal.PkController;
import com.cenluan.kit.UUIDKit;
import com.cenluan.kit.XssKit;
import com.cenluan.login.ClearLoginInterceptor;
import com.cenluan.me.call.Call;
import com.cenluan.me.message.Message;
import com.cenluan.user.User;
import com.cenluan.user.log.UserLog;
import com.jfinal.aop.Before;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.activerecord.tx.Tx;

/**
 * 投票 f
 * 
 * @author peak
 * 
 */
public class VoteController extends PkController {
	/**
	 * 列表，show参数有三个值：<br>
	 * new代表查看最新的投票，结果按创建时间倒序，也是默认值<br>
	 * hot代表查看热门投票，结果按投票人数倒序<br>
	 * mine表示查看自己的投票，显示结果是当前用户创建的投票<br>
	 */
	@ClearLoginInterceptor
	public void index() {
		User user = getSessionAttr(Const.SESSION_USER);
		String show = getPara("show");
		String order = "new";
		String createrId = null;
		if ("hot".equals(show)) {
			order = "hot";
		} else if (user != null && "mine".equals(show)) {
			createrId = user.getStr("id");
		}
		Page<Vote> page = Vote.dao.page(getPn(), 20, order, createrId);
		setPage(page);
		keepPara();
	}

	/**
	 * 添加
	 */
	public void add() {
		createToken();
	}

	/**
	 * 保存
	 */
	@Before({ VoteValidator.class, Tx.class })
	public void save() {
		User user = getSessionAttr(Const.SESSION_USER);
		Vote vote = getModel(Vote.class);
		vote.set("createrId", user.getStr("id"));
		vote.set("createTime", new Date());
		vote.set("state", Vote.STATE_ACTIVE);
		String voteId = UUIDKit.generateUUID();
		vote.set("id", voteId);
		if (!vote.save()) {
			throw new RuntimeException("保存投票失败");
		}
		String[] options = getParaValues("option");
		String optionId = UUIDKit.generateUUID();
		for (int i = 0; i < options.length; i++) {
			VoteOption option = new VoteOption();
			String content = options[i];
			option.set("content", content);
			option.set("voteId", voteId);
			option.set("id", optionId + i);
			if (!option.save()) {
				throw new RuntimeException("保存投票选项失败");
			}
		}
		// 保存用户动态
		UserLog.save(user.getStr("id"), UserLog.TYPE_CREATE_VOTE,
				vote.getStr("id"));
		redirect("/vote?show=mine");

	}

	/**
	 * 展示
	 */
	public void show() {
		Vote vote = Vote.dao.findById(getPara());
		if (Vote.STATE_DELETED.equals(vote.getStr("state"))) {
			renderError(404);
			return;
		}
		setAttr("vote", vote);
	}

	/**
	 * 返回一个只包含一个div的html页面代码
	 */
	public void div() {
		Vote vote = Vote.dao.findById(getPara());
		if (Vote.STATE_DELETED.equals(vote.getStr("state"))) {
			renderError(404);
			return;
		}
		setAttr("vote", vote);
	}

	/**
	 * 删除
	 */
	public void delete() {
		User user = getSessionAttr(Const.SESSION_USER);
		Vote vote = Vote.dao.findById(getPara());
		if (!user.isAdmin()
				&& !user.getStr("id").equals(vote.getStr("createrId"))) {
			renderError(403);
			return;
		}
		// 如果不是创建人自己删除的，发个通知
		if (!user.getStr("id").equals(vote.getStr("createrId"))) {
			String content = "我删除了你的投票\""
					+ XssKit.escapeStr(vote.getStr("title")) + "\"";
			Message.save(user.getStr("id"), vote.getStr("createrId"), content);
		}

		vote.set("state", Vote.STATE_DELETED);
		vote.keep("id", "state").update();
		setAttr("ok", true);
		renderJson();
	}

	/**
	 * 进行投票操作
	 */
	@Before(Tx.class)
	public void vote() {
		User user = getSessionAttr(Const.SESSION_USER);
		Vote vote = Vote.dao.findById(getPara());
		if (!Vote.STATE_ACTIVE.equals(vote.getStr("state"))) {
			setAttr("msg", "操作被禁止");
			renderJson();
			return;
		}
		if (vote.hasVoted(user.getStr("id"))) {
			setAttr("msg", "您已经投过票了");
			renderJson();
			return;
		}
		String[] optionIds = getParaValues("optionId");
		if (optionIds.length == 0) {
			setAttr("msg", "没有选择任何选项");
			renderJson();
			return;
		}
		if (Vote.TYPE_SINGLE.equals(vote.getStr("type"))
				&& optionIds.length != 1) {
			setAttr("msg", "该投票只支持单选");
			renderJson();
			return;
		}
		// 循环，存储投票选项关联数据
		for (String optionId : optionIds) {
			VoteOption option = VoteOption.dao.findById(optionId);
			if (!vote.getStr("id").equals(option.getStr("voteId"))) {
				throw new RuntimeException("数据不正确");
			}
			Record record = new Record();
			record.set("userId", user.getStr("id"));
			record.set("optionId", optionId);
			if (!Db.save("t_vote_option_user", record)) {
				throw new RuntimeException("存储选项与用户关联信息失败");
			}
			if (!option.addTotalVotes()) {
				throw new RuntimeException("更改选项总票数失败");
			}
		}
		if (!vote.addTotalUsers()) {
			throw new RuntimeException("更改投票总人数失败");
		}
		if (!vote.addTotalVotes(optionIds.length)) {
			throw new RuntimeException("更新总票数失败");
		}
		// 记下动态和通知
		UserLog.save(user.getStr("id"), UserLog.TYPE_JOIN_VOTE,
				vote.getStr("id"));
		// 如果是自己投自己发起的投票通知就没有意义了
		if (!user.getStr("id").equals(vote.getStr("createrId"))) {
			Call.save(user.getStr("id"), vote.getStr("createrId"),
					Call.TYPE_JOIN_VOTE, vote.getStr("id"));
		}
		setAttr("ok", true);
		renderJson();

	}
}
